﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.ComponentModel;

namespace Lists
{
    public class DataAccess
    {
        private static string errorMessage;
        public static string ErrorMessage { get { return errorMessage; } }
        private string connectionString;
        public string ConnectionString { get { return connectionString; } }
        public DataAccess()
        {
            errorMessage = string.Empty;
            connectionString = GeneralLibs.LocalSettings.ConnectString;
        }
        public DataAccess(string connectionString)
        {
            errorMessage = string.Empty;
            this.connectionString = connectionString;
        }
        /// <summary>
        /// Thực thi câu truy vấn trả về bảng
        /// </summary>
        /// <param name="query">Câu truy vấn sql</param>
        /// <returns></returns>
        public DataTable ExecuteSelect(string query)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    SqlCommand cmd = conn.CreateCommand();
                    return ExecuteSelect(cmd, query, CommandType.Text, null);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi câu truy vấn trả về bảng
        /// </summary>
        /// <param name="query">Câu truy vấn sql</param>
        /// <param name="param">Danh sách tham số của truy vấn</param>
        /// <returns></returns>
        public DataTable ExecuteSelect(string query, params SqlParameter[] param)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    SqlCommand cmd = conn.CreateCommand();
                    return ExecuteSelect(cmd, query, CommandType.Text, param);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi câu truy vấn trả về bảng
        /// </summary>
        /// <param name="cmd">SqlCommand</param>
        /// <param name="query">Câu truy vấn sql</param>
        /// <param name="type">Kiểu truy vấn (là truy vấn thông thường hay là thủ tục)</param>
        /// <param name="param">Danh sách tham số của truy vấn</param>
        /// <returns></returns>
        public DataTable ExecuteSelect(SqlCommand cmd, string query, CommandType type, params SqlParameter[] param)
        {
            try
            {
                cmd.Parameters.Clear();
                cmd.CommandText = query;
                cmd.CommandType = type;
                cmd.CommandTimeout = 2000;
                if (param != null)
                    cmd.Parameters.AddRange(param);
                SqlDataAdapter da = new SqlDataAdapter(cmd);
                DataTable dtRet = new DataTable();
                da.Fill(dtRet);
                return dtRet;
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi thủ tục trả về bảng
        /// </summary>
        /// <param name="procName">Tên thủ tục</param>
        /// <returns></returns>
        public DataTable ExecuteStoredProcedureToTable(string procName)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    SqlCommand cmd = conn.CreateCommand();
                    return ExecuteSelect(cmd, procName, CommandType.StoredProcedure, null);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi thủ tục trả về bảng
        /// </summary>
        /// <param name="procName">Tên thủ tục</param>
        /// <param name="param">Danh sách tham số</param>
        /// <returns></returns>
        public DataTable ExecuteStoredProcedureToTable(string procName, params SqlParameter[] param)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    SqlCommand cmd = conn.CreateCommand();
                    return ExecuteSelect(cmd, procName, CommandType.StoredProcedure, param);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi câu truy vấn update dữ liệu
        /// </summary>
        /// <param name="query">Câu truy vấn sql</param>
        public void ExecuteUpdate(string query)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    SqlCommand cmd = conn.CreateCommand();
                    ExecuteUpdate(cmd, query, CommandType.Text, null);
                    cmd.Dispose();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi câu truy vấn update dữ liệu
        /// </summary>
        /// <param name="query">Câu truy vấn sql</param>
        /// <param name="param">Danh sách tham số</param>
        public void ExecuteUpdate(string query, params SqlParameter[] param)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    SqlCommand cmd = conn.CreateCommand();
                    ExecuteUpdate(cmd, query, CommandType.Text, param);
                    cmd.Dispose();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi câu truy vấn update dữ liệu
        /// </summary>
        /// <param name="cmd">SqlCommand</param>
        /// <param name="query">câu truy vấn dữ liệu</param>
        /// <param name="type">Kiểu truy vân (thông thường hay thủ tục)</param>
        /// <param name="param">Danh sách tham số</param>
        public void ExecuteUpdate(SqlCommand cmd, string query, CommandType type, SqlParameter[] param)
        {
            try
            {
                cmd.Parameters.Clear();
                cmd.CommandType = type;
                cmd.CommandText = query;
                cmd.CommandTimeout = 2000;
                if (param != null) cmd.Parameters.AddRange(param);
                cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi thủ tục update dữ liệu
        /// </summary>
        /// <param name="procName">Tên thủ tục</param>
        public void ExecuteStoreProcedureToUpdate(string procName)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    SqlCommand cmd = conn.CreateCommand();
                    ExecuteUpdate(cmd, procName, CommandType.StoredProcedure, null);
                    cmd.Dispose();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi thủ tục update dữ liệu
        /// </summary>
        /// <param name="procName">Tên thủ tục</param>
        /// <param name="param">Danh sách tham số</param>
        public void ExecuteStoreProcedureToUpdate(string procName, params SqlParameter[] param)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    SqlCommand cmd = conn.CreateCommand();
                    ExecuteUpdate(cmd, procName, CommandType.StoredProcedure, param);
                    cmd.Dispose();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi truy vấn, trả về ô đầu tiên của dòng đầu tiên của kết quả
        /// </summary>
        /// <param name="cmd">SqlCommand</param>
        /// <param name="query">Câu truy vấn</param>
        /// <param name="type">Kiểu truy vấn (thông thường hay thủ tục)</param>
        /// <param name="param">Danh sách tham số</param>
        /// <returns></returns>
        public object ExecuteScalar(SqlCommand cmd, string query, CommandType type, params SqlParameter[] param)
        {
            try
            {
                cmd.CommandText = query;
                cmd.CommandType = type;
                if (param != null) cmd.Parameters.AddRange(param);
                return cmd.ExecuteScalar();
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi truy vấn, trả về ô đầu tiên của dòng đầu tiên của kết quả
        /// </summary>
        /// <param name="query">Câu truy vấn</param>
        /// <returns></returns>
        public object ExecuteScalar(string query)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    SqlCommand cmd = conn.CreateCommand();
                    return ExecuteScalar(cmd, query, CommandType.Text, null);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi truy vấn, trả về ô đầu tiên của dòng đầu tiên của kết quả
        /// </summary>
        /// <param name="query">Câu truy vấn</param>
        /// <param name="param">Danh sách tham số</param>
        /// <returns></returns>
        public object ExecuteScalar(string query, params SqlParameter[] param)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    SqlCommand cmd = conn.CreateCommand();
                    return ExecuteScalar(cmd, query, CommandType.Text, param);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi thủ tục, trả về ô đầu tiên của dòng đầu tiên của kết quả
        /// </summary>
        /// <param name="procName">Tên thủ tục</param>
        /// <returns></returns>
        public object ExecuteScalarStoredProcedure(string procName)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    SqlCommand cmd = conn.CreateCommand();
                    return ExecuteScalar(cmd, procName, CommandType.StoredProcedure, null);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        /// <summary>
        /// Thực thi thủ tục, trả về ô đầu tiên của dòng đầu tiên của kết quả
        /// </summary>
        /// <param name="procName">Tên thủ tục</param>
        /// <param name="param">Danh sách tham số</param>
        /// <returns></returns>
        public object ExecuteScalarStoredProcedure(string procName, params SqlParameter[] param)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    SqlCommand cmd = conn.CreateCommand();
                    return ExecuteScalar(cmd, procName, CommandType.StoredProcedure, param);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public static DataTable ToDataTable<T>(IList<T> data)
        {
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
            DataTable table = new DataTable();
            foreach (PropertyDescriptor prop in properties)
                table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
            foreach (T item in data)
            {
                DataRow row = table.NewRow();
                foreach (PropertyDescriptor prop in properties)
                    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                table.Rows.Add(row);
            }
            return table;
        }
    }
}
